#include "../include/pVect.h"
#include <cmath>

pVect::pVect()
{
    x = 0.0;
    y = 0.0;
    z = 0.0;
}

pVect::~pVect()
{
    //dtor
}


pVect::pVect(const pVect& v)
{
    x = v.x;
    y = v.y;
    z = v.z;
}

pVect::pVect(float x, float y, float z)
{
    this->x = x;
    this->y = y;
    this->z = z;
}

// Egalité de 2 vecteurs
bool pVect::operator==(const pVect& v) const
{
    return (x==v.x && y==v.y && z==v.z);
}

// Inégalité de 2 vecteurs
bool pVect::operator!=(const pVect& v) const
{
    return (x!=v.x || y!=v.y || z!=v.z);
}

// Affectation
pVect pVect::operator=(const pVect& v)
{
    x = v.x;
    y = v.y;
    z = v.z;
    return pVect(v.x,v.y,v.z);
}


// Addition d'un autre vecteur
pVect pVect::operator+(const pVect& v) const
{
    return pVect(x+v.x,y+v.y,z+v.z);
}

void pVect::operator+=(const pVect& v)
{
    x += v.x;
    y += v.y;
    z += v.z;
}


// Addition d'un scalaire sur toutes les composantes
pVect pVect::operator+(const float f) const
{
    return pVect(x+f,y+f,z+f);
}

void pVect::operator+=(const float f)
{
    x += f;
    y += f;
    z += f;
}


// Soustraction d'un autre vecteur
pVect pVect::operator-(const pVect& v) const
{
     return pVect(x-v.x,y-v.y,z-v.z);
}

void pVect::operator-=(const pVect& v)
{
    x -= v.x;
    y -= v.y;
    z -= v.z;
}


// Soustraction d'un scalaire sur toutes les composantes
pVect pVect::operator-(const float f) const
{
    return pVect(x-f,y-f,z-f);
}

void pVect::operator-=(const float f)
{
    x -= f;
    y -= f;
    z -= f;
}


// Multiplication de toutes les composantes par un scalaire
pVect pVect::operator*(const float f) const
{
    return pVect(x*f,y*f,z*f);
}

void pVect::operator*=(const float f)
{
    x *= f;
    y *= f;
    z *= f;
}

// division de toutes les composantes par un scalaire
pVect pVect::operator/(const float f) const
{
    return pVect(x/f,y/f,z/f);
}

void pVect::operator/=(const float f)
{
    x /= f;
    y /= f;
    z /= f;
}


// Produit vectoriel
pVect pVect::operator^(const pVect& v) const
{
    return pVect(y*v.z-z*v.y,z*v.x-x*v.z,x*v.y-y*v.x);
}

void pVect::operator^=(const pVect& v)
{
    float tx = y*v.z-z*v.y;
    float ty = z*v.x-x*v.z;
    float tz = x*v.y-y*v.x;
    x = tx;
    y = ty;
    z = tz;
}


// Produit scalaire
float pVect::operator*(const pVect& v) const
{
    return x*v.x + y*v.y + z*v.z;
}


// Norme
float pVect::norm() const
{
    return sqrt(sqrNorm());
}

// Norme
float pVect::sqrNorm() const
{
    return x*x+y*y+z*z;
}


// Normalise le vecteur
void pVect::normalize()
{
    float nr = norm();
    x = x/nr;
    y = y/nr;
    z = z/nr;
}

pVect pVect::normalizeNew() const
{
    float nr = norm();
    return pVect(x/nr,y/nr,z/nr);
}

/**
* Creer un repère ayant pour normal "this"
* @return i, j autre vecteur du repere
*/
void pVect::repere(pVect& i, pVect& j){
    pVect k = (*this);
    i = pVect(1,0,0);
    float scal = k*i;
    if(scal > 0.99){
        i = pVect(0,1,0);
    }
    j = k^i;
    i = j^k;
}
